/**
 * @Title: 功能
 * @Description: 功能描述
 * @Company: Forever Open Source Software INC.
 * @ClassName: HttpClientUtil.java
 * @Author: luxinming
 * @CreaterDate: 2014年4月26日
 * @UpdateUser: 
 * @Version: 0.1
 */
package com.foreveross.eimpc.web.util;

import com.foreveross.eimpc.web.constants.Configs;
import com.foreveross.eimpc.web.constants.Constants;
import com.foreveross.eimpc.web.exception.ApiException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;


/**
 * @ClassName: HttpClientUtil.java
 * @Description: 功能描述
 * @author: luxinming
 * @date: 2014年4月26日
 */
public class HttpClientUtil{
	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
	private static final String CHARSET_DEFAULT = "UTF-8";
	private static final String CONTENTTYPE_DEFAULT = "application/json";
	
	private static Charset getCharset(String charset){
		if (charset == null || charset.isEmpty()) {
			return null;
		}

		return Charset.forName(charset);
	}
	
	private static HttpGet setHeader(Map<String, String> headerData, HttpGet httpGet) {
		if (headerData == null || headerData.isEmpty()) {
			return httpGet;
		}
		
		for(Map.Entry<String, String> entry:headerData.entrySet()){
			httpGet.setHeader(entry.getKey(), entry.getValue());
		}
		
		return httpGet;
	}
	
	private static HttpPost postForm(String url, Map<String, String> params, Charset encode) {
		HttpPost httpost = new HttpPost(url);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();

		Set<String> keySet = params.keySet();
		for (String key : keySet) {
			nvps.add(new BasicNameValuePair(key, params.get(key)));
		}

		logger.info("set {} form entity to httppost", encode);
		httpost.setEntity(new UrlEncodedFormEntity(nvps, encode));

		return httpost;
	}
	
	private static HttpPost setHeader(Map<String, String> headerData, HttpPost httpPost) {
		if (headerData == null || headerData.isEmpty()) {
			return httpPost;
		}
		
		for(Map.Entry<String, String> entry:headerData.entrySet()){
			httpPost.setHeader(entry.getKey(), entry.getValue());
		}
		
		return httpPost;
	}
	
	private static String appendQueryMark(String uri) {
		return uri.contains("?") ? "&" : "?";
	}
	
	private static RequestConfig getRequestConfig(final Integer connectTimeout,
			final Integer socketTimeout){
		//设置请求和传输超时时间
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(socketTimeout!=null?socketTimeout:-1)				//数据传输时间
				.setConnectTimeout(connectTimeout!=null?connectTimeout:-1).build();	//连接时间
		
		return requestConfig;
	}
	
	public static String get(String url){
		return get(url, null, null, null);
	}
	
	public static String get(String url, Map<String, String> headerData, String decodeCharset){
		
		return get(url, null, headerData, decodeCharset);
	}
	
	public static String get(String url, final Map<String, String> getData,
			final Map<String, String> headerData, String decodeCharset){
		return get(url, getData, headerData, decodeCharset, null, null);
	}
	
	public static String get(String url, final Map<String, String> getData,
			final Map<String, String> headerData, String decodeCharset, final Integer connectTimeout, final Integer socketTimeout) {
		String responsePayload = null;
		StringBuffer urlBuffer = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		HttpEntity responseEntity = null;
		Charset decode = Charset.forName(CHARSET_DEFAULT);
		
		try {
			logger.debug("HttpClientUtil.get 请求参数:url={}, getData={}, headerData={}, decodeCharset={}",
					url, FastJsonUtil.getJSONString(getData), FastJsonUtil.getJSONString(headerData), decodeCharset);
			
			if (decodeCharset != null && !decodeCharset.isEmpty()) {
				decode = getCharset(decodeCharset);
			}

			if (url == null || url.isEmpty()) {
				throw new ConnectException("url must not be null");
			}

			if (null != getData && !getData.isEmpty()) {
				urlBuffer = new StringBuffer();
				urlBuffer.append(url);
				urlBuffer.append(appendQueryMark(url));

				for (Entry<String, String> entry : getData.entrySet()) {
					urlBuffer.append(entry.getKey()).append("=").append(entry.getValue());
					urlBuffer.append("&");
				}
				
				url = urlBuffer.substring(0, urlBuffer.length() - 1);
			}
			
			logger.debug("请求url:{}", url);
			HttpGet httpGet = new HttpGet(url);
			
			if (headerData != null && !headerData.isEmpty()) {
				httpGet = setHeader(headerData, httpGet);
			}
			
			if (connectTimeout != null || socketTimeout != null) {
				httpGet.setConfig(getRequestConfig(connectTimeout, socketTimeout));
			}
			
			response = httpClient.execute(httpGet);
			
			if (response == null) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());

            //token无效处理
            if(400 == response.getStatusLine().getStatusCode()){
                if (response != null) {
                    responseEntity = response.getEntity();
                }
                if (responseEntity != null) {
                    responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
                    throw new ApiException(Constants.API_Bad_Request, responsePayload);
                }
            }else if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
			}
			
			if (response != null) {
				responseEntity = response.getEntity();
			}
			
			if (responseEntity != null) {
				//status 为204时,responseEntity为null
				responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
			}

			logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);

			EntityUtils.consume(responseEntity);
			
		} catch (Exception e) {
			logger.error("Http get请求异常:{}", url);
			logger.error("Http get请求异常:", e);
            if(StringUtils.isNotBlank(responsePayload)){
                throw new ApiException(Constants.API_Bad_Request, responsePayload);
            }else {
                throw new ApiException(Constants.API_Internal, "请求远程服务错误");
            }
		} finally {
			try {
				if (null != response) {
					response.close();
				}
				httpClient.close();
			} catch (IOException e) {
				logger.error("关闭Http通道异常", e);
			}
		}
		logger.debug("HttpClientUtil.get 返回结果:responsePayload={}", responsePayload);
		return responsePayload;
	}
	
	public static byte[] getByte(String url, final Map<String, String> getData,
			final Map<String, String> headerData) {
		return getByte(url, getData, headerData, null, null);
	}
	
	public static byte[] getByte(String url, final Map<String, String> getData,
			final Map<String, String> headerData, final Integer connectTimeout, final Integer socketTimeout) {
		byte[] responsePayload = null;
		StringBuffer urlBuffer = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		HttpEntity responseEntity = null;
		try {
			logger.debug("HttpClientUtil.getByte 请求参数:url={}, getData={}, headerData={}",
					url, FastJsonUtil.getJSONString(getData), FastJsonUtil.getJSONString(headerData));
			
			if (url == null || url.isEmpty()) {
				throw new ConnectException("url must not be null");
			}

			if (null != getData && !getData.isEmpty()) {
				urlBuffer = new StringBuffer();
				urlBuffer.append(url);
				urlBuffer.append(appendQueryMark(url));

				for (Entry<String, String> entry : getData.entrySet()) {
					urlBuffer.append(entry.getKey()).append("=").append(entry.getValue());
					urlBuffer.append("&");
				}
				
				url = urlBuffer.substring(0, urlBuffer.length() - 1);
			}
			logger.debug("请求url:{}", url);
			HttpGet httpGet = new HttpGet(url);
			
			if (headerData != null && !headerData.isEmpty()) {
				httpGet = setHeader(headerData, httpGet);
			}
			
			if (connectTimeout != null || socketTimeout != null) {
				httpGet.setConfig(getRequestConfig(connectTimeout, socketTimeout));
			}
			
			response = httpClient.execute(httpGet);
			if (response == null) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());
			
			if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
			}
			
			if (response != null) {
				responseEntity = response.getEntity();
			}
			if (responseEntity != null) {
				responsePayload = EntityUtils.toByteArray(responseEntity);
			}

			logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);

			EntityUtils.consume(responseEntity);
			
		} catch (Exception e) {
			logger.error("Http getByte请求异常:{}", url);
			logger.error("Http getByte请求异常:", e);
			throw new ApiException(Constants.API_Internal, "请求远程服务错误");
		} finally {
			try {
				if (null != response) {
					response.close();
				}
				httpClient.close();
			} catch (IOException e) {
				logger.error("关闭Http通道异常", e);
			}
		}
		logger.debug("HttpClientUtil.getByte 返回结果:responsePayload={}", responsePayload);
		return responsePayload;
	}
	
	public static String post(String url, Map<String, String> postData){
		return post(url, postData, CONTENTTYPE_DEFAULT, null, null, null);
	}
	
	public static String post(String url, Map<String, String> postData, String contentType,
			Map<String, String> headerData, String encodeCharset, String decodeCharset){
		return post(url, postData, contentType, headerData, encodeCharset, decodeCharset, null, null);
	}
	
	public static String post(String url, Map<String, String> postData,
			String contentType, Map<String, String> headerData,
			String encodeCharset, String decodeCharset, final Integer connectTimeout,
			final Integer socketTimeout) {
		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		HttpEntity responseEntity = null;
		String responsePayload = "";
		Charset encode = Charset.forName(CHARSET_DEFAULT);
		Charset decode = Charset.forName(CHARSET_DEFAULT);
		
		try {
			logger.debug("HttpClientUtil.post 请求参数:url={}, postData={}, contentType={}, headerData={}, encodeCharset={}, decodeCharset={}",
					url, FastJsonUtil.getJSONString(postData), contentType, FastJsonUtil.getJSONString(headerData), encodeCharset, decodeCharset);

			if (encodeCharset != null && !encodeCharset.isEmpty()) {
				encode = getCharset(encodeCharset);
			}
			
			if (decodeCharset != null && !decodeCharset.isEmpty()) {
				decode = getCharset(decodeCharset);
			}

			httpclient = HttpClients.createDefault();

			logger.debug("请求url:{}", url);
			HttpPost httpPost = postForm(url, postData, encode);

			// 设置请求头
			if (headerData != null && !headerData.isEmpty()) {
				httpPost = setHeader(headerData, httpPost);
			}
			
			if (connectTimeout != null || socketTimeout != null) {
				httpPost.setConfig(getRequestConfig(connectTimeout, socketTimeout));
			}
			
			logger.debug("准备调用远程帐户服务，url={}，postData={}", url, postData);

			response = httpclient.execute(httpPost);

			if (response == null) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());
			
			if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
			}
			
			if (response != null) {
				responseEntity = response.getEntity();
			}
			
			if (responseEntity != null) {
				responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);

			EntityUtils.consume(responseEntity);
		} catch (Exception e) {
			logger.error("Http post请求异常:{}", url);
			logger.error("Http post请求异常:", e);
			throw new ApiException(Constants.API_Internal, "请求远程服务错误");
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpclient != null) {
					httpclient.close();
				}
			} catch (IOException e) {
				logger.error("HttpClientUtil.post destroy http request error:url={}", url);
				logger.error("HttpClientUtil.post error:", e);
			}
		}
		logger.debug("HttpClientUtil.post 返回结果:responsePayload={}", responsePayload);
		return responsePayload;
	}
	
	public static String post(String url, String postData){
		return post(url, postData, CONTENTTYPE_DEFAULT, null, null, null);
	}
	
	public static String post(String url, String postData, final Integer connectTimeout,
			final Integer socketTimeout){
		return post(url, postData, CONTENTTYPE_DEFAULT, null, null, null, connectTimeout, socketTimeout);
	}
	
	public static String post(String url, String postData, String contentType,
			Map<String, String> headerData, String encodeCharset, String decodeCharset) {
		return post(url, postData, contentType, headerData, encodeCharset, decodeCharset, null, null);
	}
	/**
	 * 
	 * @description: 功能描述
	 * @param url
	 * @param postData
	 * @param contentType
	 * @param headerData
	 * @param encodeCharset 编码字符集,编码请求数据时用之,其为null时默认采用UTF-8解码
	 * @param decodeCharset 解码字符集,解析响应数据时用之,其为null时默认采用UTF-8解码
	 * @return
	 * @return String(返回值说明)
	 * @author luxinming  2014年4月28日
	 */
	public static String post(String url, String postData, String contentType,
			Map<String, String> headerData, String encodeCharset, String decodeCharset, final Integer connectTimeout, final Integer socketTimeout) {

		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		String responsePayload = "";
		Charset encode = Charset.forName(CHARSET_DEFAULT);
		Charset decode = Charset.forName(CHARSET_DEFAULT);
		HttpEntity responseEntity = null;
		
		try {
			logger.debug("HttpClientUtil.post 请求参数:url={}, postData={}, contentType={}, headerData={}, encodeCharset={}, decodeCharset={}",
					url, postData, contentType, FastJsonUtil.getJSONString(headerData), encodeCharset, decodeCharset);
			
			if (encodeCharset != null && !encodeCharset.isEmpty()) {
				encode = getCharset(encodeCharset);
			}
			
			if (decodeCharset != null && !decodeCharset.isEmpty()) {
				decode = getCharset(decodeCharset);
			}

			httpclient = HttpClients.createDefault();

			logger.debug("请求url:{}", url);
			HttpPost httpPost = new HttpPost(url);

			// 设置请求字符编码: 默认为UTF-8
			StringEntity entity = new StringEntity(postData, encode != null ? encode : getCharset(CHARSET_DEFAULT));

			// 设置请求数据类型: 默认为application/json
			if (contentType != null && !contentType.isEmpty()) {
				// entity.setContentType(contentType != null && !contentType.isEmpty() ? contentType : CONTENTTYPE_DEFAULT);
				entity.setContentType(contentType);
			}
			
			httpPost.setEntity(entity);

			// 设置请求头
			if (headerData != null && !headerData.isEmpty()) {
				httpPost = setHeader(headerData, httpPost);
			}

			if (connectTimeout != null || socketTimeout != null) {
				httpPost.setConfig(getRequestConfig(connectTimeout, socketTimeout));
			}
			
			logger.debug("准备调用远程帐户服务，url={}，postData={}", url, postData);

			response = httpclient.execute(httpPost);
			
			if (response == null) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());

            //token无效处理
            if(400 == response.getStatusLine().getStatusCode()){
                if (response != null) {
                    responseEntity = response.getEntity();
                }
                if (responseEntity != null) {
                    responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
                    throw new ApiException(Constants.API_Bad_Request, responsePayload);
                }
            }else if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
			}
			
			if (response != null) {
				responseEntity = response.getEntity();
			}
			if (responseEntity != null) {
				responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
			}
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);
			EntityUtils.consume(responseEntity);
			
		} catch (Exception e) {
			logger.error("Http post请求异常:{}", url);
			logger.error("Http post请求异常:", e);
            if(StringUtils.isNotBlank(responsePayload)){
                throw new ApiException(Constants.API_Bad_Request, responsePayload);
            }else {
                throw new ApiException(Constants.API_Internal, "请求远程服务错误");
            }
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpclient != null) {
					httpclient.close();
				}
			} catch (IOException e) {
				logger.error("HttpClientUtil.post destroy http request error:url={}", url);
				logger.error("HttpClientUtil.post error:", e);
			}
		}
		logger.debug("HttpClientUtil.post 返回结果:responsePayload={}", responsePayload);
		return responsePayload;
	}
	
	public static String post(String url, byte[] postData, String contentType,
			Map<String, String> headerData, String decodeCharset){
		return post(url, postData, contentType, headerData, decodeCharset, null, null);
	}
	
	public static String post(String url, byte[] postData, String contentType,
			Map<String, String> headerData, String decodeCharset, final Integer connectTimeout, final Integer socketTimeout) {

		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		String responsePayload = "";
		Charset decode = Charset.forName(CHARSET_DEFAULT);
		HttpEntity responseEntity = null;
		
		try {
			logger.debug("HttpClientUtil.post 请求参数:url={}, postData={}, contentType={}, headerData={}, decodeCharset={}",
					url, Arrays.toString(postData), contentType, FastJsonUtil.getJSONString(headerData), decodeCharset);
			
			if (decodeCharset != null && !decodeCharset.isEmpty()) {
				decode = getCharset(decodeCharset);
			}

			httpclient = HttpClients.createDefault();

			logger.debug("请求url:{}", url);
			HttpPost httpPost = new HttpPost(url);

			// 设置请求字符编码: 默认为UTF-8
			ByteArrayEntity entity = new ByteArrayEntity(postData);

			// 设置请求数据类型: 默认为application/json
			entity.setContentType(contentType != null && !contentType.isEmpty() ? contentType : CONTENTTYPE_DEFAULT);

			httpPost.setEntity(entity);

			// 设置请求头
			if (headerData != null && !headerData.isEmpty()) {
				httpPost = setHeader(headerData, httpPost);
			}

			if (connectTimeout != null || socketTimeout != null) {
				httpPost.setConfig(getRequestConfig(connectTimeout, socketTimeout));
			}
			
			logger.debug("准备调用远程帐户服务，url={}，postData={}", url, postData);

			response = httpclient.execute(httpPost);
			
			if (response == null) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
			}
			
			logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());

			if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
				throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
			}
			
			if (response != null) {
				responseEntity = response.getEntity();
			}
			if (responseEntity != null) {
				responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
			}

			logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);

			EntityUtils.consume(responseEntity);
		} catch (Exception e) {
			logger.error("Http post请求异常:{}", url);
			logger.error("Http post请求异常:", e);
			throw new ApiException(Constants.API_Internal, "请求远程服务错误");
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpclient != null) {
					httpclient.close();
				}
			} catch (IOException e) {
				logger.error("HttpClientUtil.post destroy http request error:url={}", url);
				logger.error("HttpClientUtil.post error:", e);
			}
		}
		logger.debug("HttpClientUtil.post 返回结果:responsePayload={}", responsePayload);
		return responsePayload;
	}
	
	
	private static JsonMapper mapper = JsonMapper.nonEmptyMapper();
	public static void main(String[] args){
		Map<String,String> map = new HashMap<String,String>();
		map.put("appId", "myappId");
		map.put("deviceId", "test");
		map.put("secret", "mysecret");
		map.put("username", "chengbin");
		String password = "123";
		password = MD5Util.encode(password);
		System.out.println("=="+password);
		map.put("password", password);
		map.put("devicePlatform", "PcWeb");
		map.put("ssl", "true");
		map.put("encryption", "true");
		System.out.println(Configs.LOGIN_URL);
		String result = post(Configs.LOGIN_URL, mapper.toJson(map));
		System.out.println(result);
		System.out.println(Configs.GRANT_URL);
		result = get(Configs.GRANT_URL);
		System.out.println(result);
	}

    public static String postFile(String url,
                                  Map<String, Object> postData,
                                  String contentType,
                                  Map<String, String> headerData,
                                  String encodeCharset,
                                  String decodeCharset,
                                  final Integer connectTimeout,
                                  final Integer socketTimeout) {
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        HttpEntity responseEntity = null;
        String responsePayload = "";
        Charset encode = Charset.forName(CHARSET_DEFAULT);
        Charset decode = Charset.forName(CHARSET_DEFAULT);

        try {
            logger.debug("HttpClientUtil.post 请求参数:url={}, postData={}, contentType={}, headerData={}, encodeCharset={}, decodeCharset={}",
                    url,  contentType, FastJsonUtil.getJSONString(headerData), encodeCharset, decodeCharset);

            if (encodeCharset != null && !encodeCharset.isEmpty()) {
                encode = getCharset(encodeCharset);
            }

            if (decodeCharset != null && !decodeCharset.isEmpty()) {
                decode = getCharset(decodeCharset);
            }

            httpclient = HttpClients.createDefault();

            logger.debug("请求url:{}", url);
            HttpPost httpPost = new HttpPost(url);
            MultipartEntityBuilder entityBuilder  = MultipartEntityBuilder.create();
            entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            for (String key : postData.keySet()) {
                if (postData.get(key) instanceof String) {
                    entityBuilder.addPart(key, new StringBody(postData.get(key).toString(), ContentType.create("text/plain", Consts.UTF_8)));
                } else if(postData.get(key) instanceof File){
                    File file = (File)postData.get(key);
                    FileBody fileBody = new FileBody(file, file.getName());
                    entityBuilder.addPart(key, fileBody);
                } else if(postData.get(key) instanceof byte[]){
                    byte[] bytes = (byte[])postData.get(key);
                    ByteArrayBody byteArrayBody = new ByteArrayBody(bytes, "file");
                    entityBuilder.addPart(key, byteArrayBody);
                }
            }

            logger.info("set {} form entity to httppost", encode);
            httpPost.setEntity(entityBuilder.build());


            // 设置请求头
            if (headerData != null && !headerData.isEmpty()) {
                httpPost = setHeader(headerData, httpPost);
            }

            if (connectTimeout != null || socketTimeout != null) {
                httpPost.setConfig(getRequestConfig(connectTimeout, socketTimeout));
            }

            logger.debug("准备调用远程帐户服务，url={}，postData={}", url, postData);

            response = httpclient.execute(httpPost);

            if (response == null) {
                throw new ApiException(Constants.API_Internal, "请求远程服务错误,response为null");
            }

            logger.debug("调用远程帐户服务完成，获得响应，statusline={}", response.getStatusLine());

            if (200 != response.getStatusLine().getStatusCode() && 204 != response.getStatusLine().getStatusCode()) {
                throw new ApiException(Constants.API_Internal, "请求远程服务错误,statusCode=" + response.getStatusLine().getStatusCode());
            }

            if (response != null) {
                responseEntity = response.getEntity();
            }

            if (responseEntity != null) {
                responsePayload = EntityUtils.toString(responseEntity, decode != null ? decode : getCharset(CHARSET_DEFAULT));
            }

            logger.debug("调用远程帐户服务完成，获得响应，statusline={}，responsePayload={}", response.getStatusLine(), responsePayload);

            EntityUtils.consume(responseEntity);
        } catch (Exception e) {
            logger.error("Http post请求异常:{}", url);
            logger.error("Http post请求异常:", e);
            throw new ApiException(Constants.API_Internal, "请求远程服务错误");
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException e) {
                logger.error("HttpClientUtil.post destroy http request error:url={}", url);
                logger.error("HttpClientUtil.post error:", e);
            }
        }
        logger.debug("HttpClientUtil.post 返回结果:responsePayload={}", responsePayload);
        return responsePayload;
    }
}
